home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr05
/
xnot12a.zip
/
W3KEY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-16
|
13KB
|
607 lines
#ifdef MSW
/* Keyboard stuff; in reality, this code performs a lot of tedious
* mappings of Windows keycodes to something notgnu emacs understands.
* In some cases, hard-wired mappings are done - ie a key is hit and
* an entire function name is pushed into the input stream. (For more
* info on that funcky mechanism, see extend.c. I created something
* much like Meta-X <name cmd> for parsing input-to-function mapping,
* the difference being there is no echo, it handles 'interruptions'
* and is disabled during macro recording).
*
* You'll note also that the input queue is initialized, and managed here
* as well as something called the putback queue. This is to handle
* interruptions during processing of modeline stuff; the editor base
* code does not want to deal with the concept of something else being
* able to happen during a prompt, and this ughly hack got around that
* problem and a number of others too. Ugh.
*
* The worst stuff is the odd switch statements where Microsoft decided
* that most Fkeys were one kind of message, but some others weren't.
* That and the (to me) quite strange way some keys generate multiple
* messages for each press; you'll see comments to that effect.
*/
#include "jam.h"
#include "stdlib.h"
#include "def.h"
#include "keyname.h"
#include "ttydef.h"
#include "chrdef.h"
#define MAXCHARS 256
static KCHAR *kbdinput = 0;
static KCHAR *putback_kbdinput = 0;
static int kbdcount = 0;
static int putback_kbdcount = 0;
static BOOL s_IgnoreWM_CHAR = FALSE; /* WM_KEYDOWN/WM_SYSKEYDOWN may generate
* a following WM_CHAR to ignore
*/
static BOOL mapFkey(WPARAM *wKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted);
static BOOL mapKPkey(WPARAM *wKey);
/* Alloc the internal event queues
*/
void InitInput(void)
{
if (!(kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
WindowMessage("Unable to init kbdinput!", TRUE);
if (!(putback_kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
WindowMessage("Unable to init putback_kbdinput!", TRUE);
}
/* Putback kchar to to input queue; called to unwind something
* for replay.
*/
void PutbackKchar(KCHAR c)
{
if (putback_kbdcount < MAXCHARS)
{
putback_kbdinput[putback_kbdcount] = c;
putback_kbdcount++;
}
}
/* If putback'ed events, push to normal input stream now for replay.
*/
void CheckForPutback(void)
{
int i, j;
/* if not enough room, die
*/
if ((MAXCHARS - kbdcount) < putback_kbdcount)
putback_kbdcount = 0;
else
for (j = putback_kbdcount, i = 0; i < j; i++)
{
AddKchar(putback_kbdinput[i]);
putback_kbdcount--;
}
}
/* Push normal string to input buf; used all over
* to push function names and parameters into the input
* stream just as if the user had typed them.
*/
void AddString(char *s)
{
while (s && *s)
AddKchar((KCHAR)*s++);
}
/* Add kchar to internal queue of keypresses; like above,
* seems like the user just typed them in...
*/
void AddKchar(KCHAR c)
{
if (kbdcount < MAXCHARS)
{
kbdinput[kbdcount] = c;
kbdcount++;
}
else
MessageBeep((UINT)-1); /* no more space, sigh */
}
/* Return first inqueued char from event into
* pkchar (if NON_NULL) and return status.
*/
BOOL WindowReturnKCHAR(KCHAR *pkchar)
{
register int i;
BOOL result = FALSE;
/* If something, remove from queue head
* and push the queue down
* (I know, should use head/tail pointers vs this copy down
* thing, but ...)
*/
if (kbdcount > 0)
{
result = TRUE;
if (pkchar)
{
*pkchar = kbdinput[0];
kbdcount--;
for (i = 0; i < kbdcount; i++)
kbdinput[i] = kbdinput[i+1];
}
}
return(result);
}
/* Map windows event + keycode to kchar; this gets
* pretty hairy in spots.
*/
BOOL WindowMapKey(UINT msg, WPARAM wKey, LPARAM lParam)
{
BOOL ignore;
BOOL bShifted = (GetKeyState(VK_SHIFT) < 0)? 1 : 0;
BOOL bCtrled = (GetKeyState(VK_CONTROL) < 0)? 1 : 0;
BOOL bAlted = (GetKeyState(VK_MENU) < 0)? 1 : 0;
/* Events to ignore - we see them in multiple ways. It
* makes sense to someone.
*/
if (wKey == VK_SHIFT || wKey == VK_CONTROL ||
wKey == VK_CAPITAL || wKey == VK_MENU)
return (FALSE);
/* Pre-processed stuff, with simple mapping
*/
if (msg == WM_CHAR) /* Windows has created something useful */
{
ignore = s_IgnoreWM_CHAR;
s_IgnoreWM_CHAR = FALSE; /* reset */
/* A prior event triggered this wm_char, so it's
* not useful.
*/
if (ignore)
return(FALSE);
switch (wKey)
{
case ' ':
if (bCtrled) /* a hard-wired key, cntrl-space */
{
ExtendedFunction(function_name(setmark));
return (TRUE);
}
else
break;
case CCHR('H'):
if (!bCtrled) /* must be backspace key */
return(FALSE); /* backspace key sends message w/o cntrl key */
case CCHR('I'): /* tab is hardwired to C-align function */
if (bShifted) /* but cntrl or shift tab is the real thing */
{
ExtendedFunction(function_name(hardtab));
return(TRUE);
}
}
AddKchar((KCHAR)wKey);
return(TRUE);
}
/* Keys otherwise eaten
*/
else if (msg == WM_KEYDOWN)
{
switch(wKey)
{
case VK_TAB: /* tab is hardwired to C-align function */
if (bCtrled)
{
ExtendedFunction(function_name(hardtab));
return(TRUE);
}
return(FALSE);
case VK_BACK:
wKey = 0x7f; /* ttyio mapped it this way too, ick ! */
break;
case VK_DELETE:
if (bCtrled) /* Talk about your hardwired functions! */
{ /* cntrl-delete wipes a line from any position */
ExtendedFunction(function_name(gotobol));
ExtendedFunction(function_name(killline));
ExtendedFunction(function_name(killline));
return(TRUE);
}
else if (bShifted) /* This is hardwired too */
{
ExtendedFunction(function_name(delbword));
return(TRUE);
}
else
wKey = KDELETE;
break;
case VK_INSERT:
wKey = KINSERT;
break;
case VK_HOME:
if (bCtrled)
wKey = KCHOME;
else
wKey = KHOME;
break;
case VK_END:
if (bCtrled)
wKey = KCEND;
else
wKey = KEND;
break;
case VK_RIGHT:
if (bCtrled)
wKey = KCRIGHT;
else
wKey = KRIGHT;
break;
case VK_LEFT:
if (bCtrled)
wKey = KCLEFT;
else
wKey = KLEFT;
break;
case VK_DOWN:
if (bCtrled)
{
if (bAlted) /* Down key hardwired for cntrl/alt mix */
ExtendedFunction(function_name(nextwind));
else
ExtendedFunction(function_name(forw1page));
return (TRUE);
}
else
wKey = KDOWN;
break;
case VK_UP:
if (bCtrled)
{
if (bAlted) /* Up key hardwired for cntrl/alt mix */
ExtendedFunction(function_name(prevwind));
else
ExtendedFunction(function_name(back1page));
return (TRUE);
}
else
wKey = KUP;
break;
case VK_PRIOR:
if (bCtrled)
wKey = KCPGUP;
else
wKey = KPGUP;
break;
case VK_NEXT:
if (bCtrled)
wKey = KCPGDN;
else
wKey = KPGDN;
break;
case VK_F1:
case VK_F2:
case VK_F3:
case VK_F4:
case VK_F5:
case VK_F6:
case VK_F7:
case VK_F8:
case VK_F9:
case VK_F10: /* only seen in WM_SYSKEYDOWN, why? */
case VK_F11:
case VK_F12:
if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
return (FALSE);
break;
/* keypad keys
*/
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9:
case VK_ADD:
case VK_MULTIPLY:
case VK_SUBTRACT:
case VK_DECIMAL:
case VK_DIVIDE:
case VK_EXECUTE:
case VK_NUMLOCK:
if (!mapKPkey(&wKey))
return (FALSE);
break;
/* Alphanumerics which don't generate WM_CHAR msgs
* when the cntrl key is down (beats me why!?)
*/
case 'T':
case 'P':
case 'R':
case 'Q':
if (bCtrled)
{
wKey = CCHR(wKey); /* really is cntrl-* this time */
break;
}
/* FALLTHRU */
/* NOTE if not known char, OR possible duplicate,
* do not process
*/
case VK_RETURN:
default:
return(FALSE);
}
AddKchar((KCHAR)wKey);
return(TRUE);
}
/* Why on why is only F10 a WM_SYSKEYDOWN??
*/
else if (msg == WM_SYSKEYDOWN)
{
switch(wKey)
{
case VK_F1:
case VK_F2:
case VK_F3:
case VK_F4:
case VK_F5:
case VK_F6:
case VK_F7:
case VK_F8:
case VK_F9:
case VK_F10:
case VK_F11:
case VK_F12:
if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
return (FALSE);
break;
default:
return (FALSE);
}
AddKchar((KCHAR)wKey);
return(TRUE);
}
/* Keys with meta-bit set
*/
else if (msg == WM_SYSCHAR)
{
switch(wKey)
{
default:
wKey |= METABIT;
break;
}
AddKchar((KCHAR)wKey);
return(TRUE);
}
/* Unsupported key/message combination
*/
return (FALSE);
}
/* Function key mapping - broken out for ease of
* mapping.
*/
static BOOL mapFkey(WPARAM *pwKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted)
{
WPARAM wKey = *pwKey;
BOOL mapped = TRUE;
switch(wKey)
{
case VK_F1:
if (bShifted && bCtrled) wKey = KCSF1;
else if (bShifted) wKey = KSF1;
else if (bCtrled) wKey = KCF1;
else if (bAlted) wKey = KMF1;
else wKey = KF1;
break;
case VK_F2:
if (bShifted && bCtrled) wKey = KCSF2;
else if (bShifted) wKey = KSF2;
else if (bCtrled) wKey = KCF2;
else if (bAlted) wKey = KMF2;
else wKey = KF2;
break;
case VK_F3:
if (bShifted && bCtrled) wKey = KCSF3;
else if (bShifted) wKey = KSF3;
else if (bCtrled) wKey = KCF3;
else if (bAlted) wKey = KMF3;
else wKey = KF3;
break;
case VK_F4:
if (bShifted && bCtrled) wKey = KCSF4;
else if (bShifted) wKey = KSF4;
else if (bCtrled) wKey = KCF4;
else if (bAlted) wKey = KMF4;
else wKey = KF4;
break;
case VK_F5:
if (bShifted && bCtrled) wKey = KCSF5;
else if (bShifted) wKey = KSF5;
else if (bCtrled) wKey = KCF5;
else if (bAlted) wKey = KMF5;
else wKey = KF5;
break;
case VK_F6:
if (bShifted && bCtrled) wKey = KCSF6;
else if (bShifted) wKey = KSF6;
else if (bCtrled) wKey = KCF6;
else if (bAlted) wKey = KMF6;
else wKey = KF6;
break;
case VK_F7:
if (bShifted && bCtrled) wKey = KCSF7;
else if (bShifted) wKey = KSF7;
else if (bCtrled) wKey = KCF7;
else if (bAlted) wKey = KMF7;
else wKey = KF7;
break;
case VK_F8:
if (bShifted && bCtrled) wKey = KCSF8;
else if (bShifted) wKey = KSF8;
else if (bCtrled) wKey = KCF8;
else if (bAlted) wKey = KMF8;
else wKey = KF8;
break;
case VK_F9:
if (bShifted && bCtrled) wKey = KCSF9;
else if (bShifted) wKey = KSF9;
else if (bCtrled) wKey = KCF9;
else if (bAlted) wKey = KMF9;
else wKey = KF9;
break;
case VK_F10:
if (bShifted && bCtrled) wKey = KCSF10;
else if (bShifted) wKey = KSF10;
else if (bCtrled) wKey = KCF10;
else if (bAlted) wKey = KMF10;
else wKey = KF10;
break;
case VK_F11:
if (bShifted && bCtrled) wKey = KCSF11;
else if (bShifted) wKey = KSF11;
else if (bCtrled) wKey = KCF11;
else if (bAlted) wKey = KMF11;
else wKey = KF11;
break;
case VK_F12:
if (bShifted && bCtrled) wKey = KCSF12;
else if (bShifted) wKey = KSF12;
else if (bCtrled) wKey = KCF12;
else if (bAlted) wKey = KMF12;
else wKey = KF12;
break;
default:
mapped = FALSE;
}
*pwKey = wKey;
return (mapped);
}
/* Keypadkey mapping - only partially useful since some
* keys change in value if NUM LOCK is on, which of course
* messes me up big time.
*/
static BOOL mapKPkey(WPARAM *pwKey)
{
WPARAM wKey = *pwKey;
BOOL mapped = TRUE;
switch(wKey)
{
case VK_NUMPAD0:
wKey = KP0;
break;
case VK_NUMPAD1:
wKey = KP1;
break;
case VK_NUMPAD2:
wKey = KP2;
break;
case VK_NUMPAD3:
wKey = KP3;
break;
case VK_NUMPAD4:
wKey = KP4;
break;
case VK_NUMPAD5:
wKey = KP5;
break;
case VK_NUMPAD6:
wKey = KP6;
break;
case VK_NUMPAD7:
wKey = KP7;
break;
case VK_NUMPAD8:
wKey = KP8;
break;
case VK_NUMPAD9:
wKey = KP9;
break;
case VK_ADD:
wKey = KPADD;
break;
case VK_MULTIPLY:
wKey = KPMUL;
break;
case VK_SUBTRACT:
wKey = KPSUB;
break;
case VK_DECIMAL:
wKey = KPDEL;
break;
case VK_DIVIDE:
wKey = KPDIV;
break;
case VK_NUMLOCK:
wKey = KPNUMLK;
break;
case VK_EXECUTE:
wKey = KPENTER;
break;
default:
mapped = FALSE;
}
*pwKey = wKey;
s_IgnoreWM_CHAR = mapped; /* generated an event to ignore? */
return (mapped);
}
#endif